package com.kb.design.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.kb.design.dto.QueryChartDTO;
import com.kb.design.entity.DesignOrder;
import com.kb.design.entity.DesignProject;
import com.kb.design.enums.DesignStatus;
import com.kb.design.enums.ProjectStatus;
import com.kb.design.mapper.postgreSQL.*;
import com.kb.design.service.AdminHomeService;
import com.kb.design.service.CustomUserService;
import com.kb.design.service.DeptService;
import com.kb.design.util.DateUtils;
import com.kb.design.vo.chart.OrderDataVO;
import com.kb.design.vo.chart.ProjectNodeInfoChartVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Service
@DS("slave-1")
public class AdminHomeServiceImpl implements AdminHomeService {

    /**
     * 默认查询当前月的数据
     * ==================================================================================================================================
     */

    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private DesignOrderMapper designOrderMapper;
    @Resource
    private CustomUserMapper userMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private DesignDeptMapper designDeptMapper;
    @Resource
    private DesignPostMapper postMapper;
    @Resource
    private CustomUserService userService;

    @Override
    public ProjectNodeInfoChartVO projectNodeInfo(QueryChartDTO queryChartDTO) {
        ProjectNodeInfoChartVO projectNodeInfoChart  = new ProjectNodeInfoChartVO();

        List<DesignProject> projectList = getProjectListByMonth(0);  // 本月
        List<DesignProject> lastMonthData = getProjectListByMonth(-1);     // 上月

        long count = 0;
        BigDecimal totalPinAmount = null;
        long lastCount = 0;
        BigDecimal lastTotalPinAmount = null;
        if(CollectionUtils.isNotEmpty(projectList)){
            //状态 projectStatusAuxiliary
            count = projectList.stream().filter(project -> project.getProjectStatusAuxiliary().compareTo(ProjectStatus.FINISH.getIndex()) == 0).count();
            projectNodeInfoChart.setProjectCount( BigDecimal.valueOf(count));
             totalPinAmount = projectList.stream()
                    .filter(project -> project.getProjectStatusAuxiliary().compareTo(ProjectStatus.FINISH.getIndex()) == 0)
                    .map(DesignProject::getPinAmount)
                    .filter(Objects::nonNull) // 避免空值
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            projectNodeInfoChart.setPinCount(totalPinAmount);
        }
        //上个月的项目数 pin数计算
        if(CollectionUtils.isNotEmpty(lastMonthData)){
             lastCount = lastMonthData.stream().filter(project -> project.getProjectStatusAuxiliary().compareTo(ProjectStatus.FINISH.getIndex()) == 0).count();
             lastTotalPinAmount = lastMonthData.stream()
                    .filter(project -> project.getProjectStatusAuxiliary().compareTo(ProjectStatus.FINISH.getIndex()) == 0)
                    .map(DesignProject::getPinAmount)
                    .filter(Objects::nonNull) // 避免空值
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        //环比计算
        if (lastCount != 0){
            double growthRate = (double) (lastCount - count) / lastCount;
            projectNodeInfoChart.setProjectMonthComparison(
                    BigDecimal.valueOf(growthRate)
                            .setScale(2, RoundingMode.HALF_UP)
            );
        }
        if (lastTotalPinAmount != null && !lastTotalPinAmount.equals(BigDecimal.ZERO)){
            projectNodeInfoChart.setPinMonthComparison((lastTotalPinAmount.subtract(totalPinAmount).divide(lastTotalPinAmount, 2, RoundingMode.HALF_UP)));
        }
        if (totalPinAmount != null && !totalPinAmount.equals(BigDecimal.ZERO)){
            projectNodeInfoChart.setBonus(totalPinAmount.multiply(BigDecimal.valueOf(0.47)));
        }

        //节点统计
        List<Map<String, Object>> nodeCountList = new ArrayList<>();
        //封装中
        long pageCount = projectList.stream().filter(project -> project.getStatus().compareTo(DesignStatus.ENCAPSULATION.getIndex()) == 0).count();
        BigDecimal pageTotalPinAmount = projectList.stream()
                .filter(project -> project.getStatus().compareTo(DesignStatus.ENCAPSULATION.getIndex()) == 0)
                .map(DesignProject::getPinAmount)
                .filter(Objects::nonNull) // 避免空值
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        this.projectNode(pageCount, pageTotalPinAmount, nodeCountList);
        //设计中
        long designCount = projectList.stream().filter(project -> project.getStatus().compareTo(DesignStatus.DESIGN.getIndex()) == 0).count();
        BigDecimal designTotalPinAmount = projectList.stream()
                .filter(project -> project.getStatus().compareTo(DesignStatus.DESIGN.getIndex()) == 0)
                .map(DesignProject::getPinAmount)
                .filter(Objects::nonNull) // 避免空值
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        this.projectNode(designCount, designTotalPinAmount, nodeCountList);
        //检查中
        long checkCount = projectList.stream().filter(project -> project.getStatus().compareTo(DesignStatus.CHECK.getIndex()) == 0).count();
        BigDecimal checkTotalPinAmount = projectList.stream()
                .filter(project -> project.getStatus().compareTo(DesignStatus.CHECK.getIndex()) == 0)
                .map(DesignProject::getPinAmount)
                .filter(Objects::nonNull) // 避免空值
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        this.projectNode(checkCount, checkTotalPinAmount, nodeCountList);
        //待交付 等分配奖金
        long deliveryBoardCount = projectList.stream().filter(project -> project.getStatus().compareTo(DesignStatus.CASTING_BOARD.getIndex()) == 0).count();
        BigDecimal deliveryBoardTotalPinAmount = projectList.stream()
                .filter(project -> project.getStatus().compareTo(DesignStatus.CASTING_BOARD.getIndex()) == 0)
                .map(DesignProject::getPinAmount)
                .filter(Objects::nonNull) // 避免空值
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        this.projectNode(deliveryBoardCount, deliveryBoardTotalPinAmount, nodeCountList);
        //待分配奖金
        long castingBoardCount = projectList.stream().filter(project -> project.getStatus().compareTo(DesignStatus.BONUS_DISTRIBUTION.getIndex()) == 0).count();
        BigDecimal castingBoardTotalPinAmount = projectList.stream()
                .filter(project -> project.getStatus().compareTo(DesignStatus.BONUS_DISTRIBUTION.getIndex()) == 0)
                .map(DesignProject::getPinAmount)
                .filter(Objects::nonNull) // 避免空值
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        this.projectNode(castingBoardCount, castingBoardTotalPinAmount, nodeCountList);

        projectNodeInfoChart.setNodeCountList(nodeCountList);
        return projectNodeInfoChart;
    }

    @Override
    public Map<String, Object> queryOrderData(QueryChartDTO queryChartDTO) {
        Map<String, Object> map = new HashMap<>();
        map.put("totalAmount", BigDecimal.ZERO);
        map.put("totalOrder", BigDecimal.ZERO);
        //根据入参类型获取查询范围 1 当天 2 当月 3 当季度
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startDateTime;
        LocalDateTime endDateTime;

        switch (queryChartDTO.getDateType()) {
            case "1": // 今天
                startDateTime = now.with(LocalTime.MIN);
                endDateTime = now.with(LocalTime.MAX);
                break;
            case "2": // 本月
                startDateTime = now.withDayOfMonth(1).with(LocalTime.MIN);
                endDateTime = now.withDayOfMonth(now.getMonth().length(now.getYear() % 4 == 0)).with(LocalTime.MAX);
                break;
            case "3": // 本季度
                startDateTime = DateUtils.getStartOfCurrentQuarter(now);
                endDateTime = DateUtils.getEndOfCurrentQuarter(now);
                break;
            default:
                // 默认本月
                startDateTime = now.withDayOfMonth(1).with(LocalTime.MIN);
                endDateTime = now.withDayOfMonth(now.getMonth().length(now.getYear() % 4 == 0)).with(LocalTime.MAX);
                break;
        }
        LambdaQueryWrapper<DesignOrder> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.between(DesignOrder::getOrderDate, startDateTime, endDateTime);
        List<DesignOrder> designOrderList = designOrderMapper.selectList(queryWrapper);
        List<OrderDataVO> orderDataVOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(designOrderList)){
                // 按 dept2 分组
            Map<String, List<DesignOrder>> groupedByDept2 = designOrderList.stream()
                    .collect(Collectors.groupingBy(order ->
                            order.getDept2() != null ? order.getDept2() : "unknown"));

            // 取出 groupedByDept2 中 value 数量最多的前 5 个 entry
            Map<String, List<DesignOrder>> top5ByDept2 = groupedByDept2.entrySet().stream()
                    .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size())) // 按数量降序排序
                    .limit(5)
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            Map.Entry::getValue,
                            (existing, replacement) -> existing, // 如果 key 冲突保留旧值
                            LinkedHashMap::new // 保持排序顺序
                    ));

            // 存放结果
            BigDecimal totalOrdersCount = BigDecimal.ZERO;
            BigDecimal totalAmountSum = BigDecimal.ZERO;
            for (Map.Entry<String, List<DesignOrder>> entry : top5ByDept2.entrySet()) {
                String deptName = entry.getKey();
                List<DesignOrder> orders = entry.getValue();
                OrderDataVO orderDataVO = new OrderDataVO();
                // 计算当前部门的订单数
                int orderCount = orders.size();
                // 新增：逐个订单计算未税金额
                BigDecimal totalDividedAmount = BigDecimal.ZERO;
                for (DesignOrder order : orders) {
                    BigDecimal totalAmount = order.getTotalAmount();
                    Integer invType = order.getInvType(); // 获取税率类型

                    if (totalAmount == null) continue;

                    if (invType == null || invType <= 0) {
                        invType = 6; // 默认13%税率
                    }

                    // 计算：未税金额 = 含税金额 / (1 + 税率/100)
                    BigDecimal taxRate = BigDecimal.valueOf(invType / 100.0);
                    BigDecimal preTaxAmount = totalAmount.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);

                    totalDividedAmount = totalDividedAmount.add(preTaxAmount);
                }
                // 放入每个部门的统计信息
                orderDataVO.setAmount(totalDividedAmount);
                orderDataVO.setAreaName(deptName);
                orderDataVO.setOrderCount(orderCount);

                orderDataVOList.add(orderDataVO);
                // 累加到总计
                totalOrdersCount = totalOrdersCount.add(BigDecimal.valueOf(orderCount));
                totalAmountSum = totalAmountSum.add(totalDividedAmount);
            }

            // 添加总计到结果中
            map.put("totalAmount", totalAmountSum);
            map.put("totalOrder", totalOrdersCount);
        }

        map.put("orderDataVOList", orderDataVOList);
        return map;
    }

    @Override
    public Map<String, Object> orderCountInfo(QueryChartDTO queryChartDTO) {
        Map<String, Object> map = new HashMap<>();
        map.put("orderCount", 0);
        map.put("startOrderCount",0);
        map.put("noOrderCount",0);
        //查询当天的订单数据
        LocalDate now = LocalDate.now();

        List<DesignOrder> designOrderList = designOrderMapper.selectList(Wrappers.lambdaQuery(DesignOrder.class).ge(DesignOrder::getOrderDate, now));
        if (CollectionUtils.isNotEmpty(designOrderList)){
            map.put("orderCount", designOrderList.size());
            //status == 2的数据
//            map.put("startOrderCount", designOrderList.stream().filter(order -> order.getStatus().compareTo(2) == 0).count());
        }
        //今日项目数
        List<DesignProject> projectList = projectMapper.selectList(Wrappers.lambdaQuery(DesignProject.class).ge(DesignProject::getCreateTime, now));
        if (CollectionUtils.isNotEmpty(projectList)){
            //orderId为空的数据
            map.put("noOrderCount", projectList.stream().filter(project -> project.getOrderId() == null).count());
            //今日项目数
            map.put("startOrderCount", projectList.size());
        }
        return map;
    }

    public void projectNode(long castingBoardCount, BigDecimal castingBoardTotalPinAmount, List<Map<String, Object>> nodeCountList){
        Map<String, Object> map = new HashMap<>();
        map.put("count", castingBoardCount);
        map.put("totalPinAmount", castingBoardTotalPinAmount);
        nodeCountList.add(map);
    }
    public List<DesignProject> getProjectListByMonth(int monthOffset) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startOfMonth = now.plusMonths(monthOffset).withDayOfMonth(1).with(LocalTime.MIN);
        LocalDateTime endOfMonth = startOfMonth.withDayOfMonth(startOfMonth.getMonth().length(startOfMonth.getYear() % 4 == 0))
                .with(LocalTime.MAX);

        LambdaQueryWrapper<DesignProject> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.between(DesignProject::getCreateTime, startOfMonth, endOfMonth);
        return projectMapper.selectList(queryWrapper);
    }
}
